package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.JSObject

////////////////////
// Declarative Content
////////////////////
/**
 * Use the `Browser.declarativeContent` API to take actions depending on the content of a page, without requiring permission to read the page's content.
 *
 * Permissions: "declarativeContent"
 */
interface DeclarativeContent {
    // Provides the Declarative Event API consisting of addRules, removeRules, and getRules.
    val onPageChanged: Events.Event<VoidFunction>

    // Matches the state of a web page based on various criteria.
    data class PageStateMatcher(
        // Matches if all of the CSS selectors in the array match displayed elements in a frame with
        // the same origin as the page's main frame.
        // All selectors in this array must be compound selectors to speed up matching.
        // Note: Listing hundreds of CSS selectors or listing CSS selectors that match hundreds of
        // times per page can slow down web sites.
        var css: List<String>?,
        // Matches if the bookmarked state of the page is equal to the specified value. Requres the bookmarks permission.
        @ChromeMinVersion(45)
        var isBookmarked: Boolean?,
        /** Optional. Filters URLs for various criteria. See event filtering. All criteria are case sensitive.  */
        var pageUrl: Events.UrlFilter?,
    )

    // Declarative event action that injects a content script.
    // WARNING: This action is still experimental and is not supported on stable builds of Chrome.
    data class RequestContentScript(
        // Whether the content script runs in all frames of the matching page, or in only the top frame.
        // Default is false.
        var allFrames: Boolean?,
        // Names of CSS files to be injected as a part of the content script.
        var css: List<String>?,
        // Names of JavaScript files to be injected as a part of the content script.
        var js: List<String>?,
        // Whether to insert the content script on about:blank and about:srcdoc. Default is false.
        var matchAboutBlank: Boolean?
    )

    // Declarative event action that sets the n-dip square icon for the extension's page action or
    // browser action while the corresponding conditions are met.
    // This action can be used without host permissions, but the extension must have a page or browser action.
    //
    //Exactly one of imageData or path must be specified. Both are dictionaries mapping a number
    // of pixels to an image representation. The image representation in imageData is an ImageData object;
    // for example, from a canvas element, while the image representation in path is the path to an
    // image file relative to the extension's manifest. If scale screen pixels fit into a
    // device-independent pixel, the scale * n icon is used.
    // If that scale is missing, another image is resized to the required size.

    data class SetIcon(
        // Either an ImageData object or a dictionary {size -> ImageData} representing an icon to be set.
        // If the icon is specified as a dictionary, the image used is chosen depending on the screen's pixel density. I
        // f the number of image pixels that fit into one screen space unit equals scale,
        // then an image with size scale * n is selected, where n is the size of the icon in the UI.
        // At least one image must be specified. Note that details.imageData = foo is equivalent to details.imageData = {'16': foo}.
        var imageData: ImageDataOrObject?
    )

    // A declarative event action that sets the extension's toolbar action to an enabled state
    // while the corresponding conditions are met.
    // This action can be used without host permissions.
    // If the extension has the activeTab permission, clicking the page action grants access to the active tab.
    //
    //On pages where the conditions are not met the extension's toolbar action will be grey-scale,
    // and clicking it will open the context menu, instead of triggering the action.
    @ChromeMinVersion(97)
    class ShowAction

    // A declarative event action that sets the extension's page action to an enabled state
    // while the corresponding conditions are met.
    // This action can be used without host permissions, but the extension must have a page action.
    // If the extension has the activeTab permission, clicking the page action grants access to the active tab.
    //
    //On pages where the conditions are not met the extension's toolbar action will be grey-scale,
    // and clicking it will open the context menu, instead of triggering the action.
    @Deprecated(
        "Please use declarativeContent.ShowAction.",
        ReplaceWith("Please use declarativeContent.ShowAction.")
    )
    class ShowPageAction

    sealed class ImageDataOrObject {
        data class ImageData(val imageData: ImageData) :
            ImageDataOrObject()

        data class Object(val obj: JSObject) : ImageDataOrObject()
    }
}